<?php
final class SPDO extends PDO 
{
	static private  $options;
	static private  $instance;
	static private  $constructIsPrivate = true;
	
	public function __construct()
	 {
		 if (self::$constructIsPrivate) {
			trigger_error('Call to private ' . __CLASS__ . 
			'::__construct() from invalid context', E_USER_ERROR);
		 }
		 
		 try {
			$config = Config::singleton();
			 
			 parent::__construct('mysql:host=' . $config->get('dbhost') . ';dbname=' . $config->get('dbname'), $config->get('dbuser'), $config->get('dbpass'));
			 $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);			 
		 
		 } catch (PDOException $e) {
			echo 'Connection failed: ' . $e->getMessage();
		 }
	 }


static public function getInstance()
 {
 if (!isset(self::$instance))
 {
 self::$constructIsPrivate = false;
 $c = __CLASS__;
 self::$instance = new $c;
 self::$constructIsPrivate = true;
 }
 return self::$instance;
 }
 
 /**
 * Initiates a transaction
 *
 * @access public
 * @return bool
 */
 public function beginTransaction()
 {
 return parent::beginTransaction();
 }
 
 /**
 * Commits a transaction 
 *
 * @access public
 * @return bool
 */
 public function commit()
 {
 return parent::commit();
 }
 
 /**
 * Fetch the SQLSTATE associated with the last operation on the database handle
 *
 * @access public
 * @return string
 */
 public function errorCode()
 {
 return parent::errorCode();
 }
 
 /**
 * Fetch extended error information associated with the last operation on the database handle
 *
 * @access public
 * @return array
 */
 public function errorInfo()
 {
 return parent::errorInfo();
 }
 
 /**
 * Execute an SQL statement and return the number of affected rows
 *
 * @access public
 * @param  string $statement
 * @return int
 */
 public function exec($statement)
 {
 return parent::exec($statement);
 }
 
 /**
 * Return an array of available PDO drivers
 *
 * @access static public
 * @return array
 */
 static public function getAvailableDrivers()
 {
 return parent::getAvailableDrivers();
 }
 
 /**
 * Returns the ID of the last inserted row or sequence value 
 *
 * @access public
 * @param  string[optional] $name
 * @return string
 */
 public function lastInsertId($name = null)
 {
 return parent::lastInsertId($name);
 }
 
 /**
 * Prepares a statement for execution and returns a statement object
 *
 * @access public
 * @param  string $statement
 * @param  array  $driver_options
 * @return PDOStatement
 */
 public function prepare($statement, $driver_options = array() )
 {
 return parent::prepare($statement, $driver_options);
 }
 
 /**
 * Executes an SQL statement, returning a result set as a PDOStatement object
 *
 * @access public
 * @param  string $statement
 * @return PDOStatement
 */
 public function query()
 {
 $args = func_get_args();
 switch(func_num_args()) {
 case 1:
 return parent::query($args[0]);
 break;
 case 2:
 return parent::query($args[0], $args[1]);
 break;
 case 3:
 return parent::query($args[0], $args[1], $args[2]);
 break;
 case 4:
 return parent::query($args[0], $args[1], $args[2], $args[3]);
 break;
 }
 }
 
 /**
 * Quotes a string for use in a query
 *
 * @access public
 * @param  string        $string
 * @param  int[optional] $parameter_type
 * @return string
 */
 public function quote($string, $parameter_type = PDO::PARAM_STR )
 {
 return parent::quote($string, $parameter_type);
 }
 
 /**
 * Rolls back a transaction 
 *
 * @access public
 * @return bool
 */
 public function rollBack()
 {
 return parent::rollBack();
 }
 
 /**
 * Set an attribute
 *
 * @access public
 * @param  int   $attribute
 * @param  mixed $value
 * @return bool
 */
 public function setAttribute($attribute, $value)
 {
 return parent::setAttribute($attribute, $value);
 }
 
 /**
 * Bind a column to a PHP variable 
 *
 * @access public
 * @param  mixed           $column
 * @param  mixed           $param
 * @param  int[optional]   $type
 * @param  int[optional]   $maxlen
 * @param  mixed[optional] $driverdata
 * @return bool
 */
 public function bindColumn($column, &$param, $type = null, $maxlen = null, $driverdata = null)
 {
 return parent::bindColumn($column, &$param, $type, $maxlen, $driverdata);
 }
 
 /**
 * Binds a parameter to the specified variable name
 *
 * @access public
 * @param  mixed           $parameter 
 * @param  mixed           $variable 
 * @param  int[optional]   $data_type
 * @param  int[optional]   $length
 * @param  mixed[optional] $driver_options
 * @return bool
 */
 public function bindParam($parameter, &$variable, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null)
 {
 return parent::bindParam($parameter, &$variable, $data_type, $length, $driver_options);
 }
 
 /**
 * Binds a value to a parameter
 *
 * @access public
 * @param  mixed         $parameter
 * @param  mixed         $value
 * @param  int[optional] $data_type
 * @return bool
 */
 public function bindValue($parameter, $value, $data_type = PDO::PARAM_STR)
 {
 return parent::bindValue($parameter, $value, $data_type);
 }
 
 /**
 * Closes the cursor, enabling the statement to be executed again
 *
 * @access public
 * @return bool
 */
 public function closeCursor()
 {
 return parent::closeCursor();
 }
 
 /**
 * Returns the number of columns in the result set
 *
 * @access public
 * @return int
 */
 public function columnCount()
 {
 return parent::columnCount();
 }
 
 /**
 * Dump a SQL prepared command
 *
 * @access public
 */
 public function debugDumpParams()
 {
 return parent::debugDumpParams();
 }
 
 /**
 * Executes a prepared statement 
 *
 * @access public
 * @param  array $input_parameters
 * @return bool
 */
 public function execute($input_parameters = array())
 {
 return parent::execute($input_parameters);
 }
 
 /**
 * Fetches the next row from a result set
 *
 * @access public
 * @param  int[optional] $fetch_style
 * @param  int[optional] $cursor_orientation
 * @param  int[optional] $cursor_offset
 * @return mixed
 */
 public function fetch($fetch_style = PDO::FETCH_BOTH, $cursor_orientation = PDO::FETCH_ORI_NEXT, $cursor_offset = 0)
 {
 return parent::fetch($fetch_style, $cursor_orientation, $cursor_offset);
 }
 
 /**
 * Returns an array containing all of the result set rows
 *
 * @access public
 * @param  int[optional] $fetch_style
 * @param  int[optional] $column_index
 * @param  array         $ctor_args 
 * @return array
 */
 public function fetchAll($fetch_style = PDO::FETCH_BOTH, $column_index = 0 , $ctor_args = array())
 {
 return parent::fetchAll($fetch_style, $column_index, $ctor_args);
 }
 
 /**
 * Returns a single column from the next row of a result set
 *
 * @access public
 * @param  int[optional] $column_number
 * @return string
 */
 public function fetchColumn($column_number = 0)
 {
 return parent::fetchColumn($column_number);
 }
 
 /**
 * Fetches the next row and returns it as an object
 *
 * @access public
 * @param  string[optional] $class_name
 * @param  array            $ctor_args
 * @return mixed
 */
 public function fetchObject($class_name = 'stdClass', $ctor_args = null)
 {
 return parent::fetchObject($class_name, $ctor_args);
 }
 
 /**
 * Retrieve a attribute
 *
 * @access public
 * @param  int $attribute
 * @return mixed
 */
 public function getAttribute($attribute)
 {
 return parent::getAttribute($attribute);
 }
 
 /**
 * Returns metadata for a column in a result set
 *
 * @access public
 * @param  int $column
 * @return array
 */
 public function getColumnMeta($column)
 {
 return parent::getColumnMeta($column);
 }
 
 /**
 * Advances to the next rowset in a multi-rowset statement handle
 *
 * @access public
 * @return bool
 */
 public function nextRowset()
 {
 return parent::nextRowset();
 }
 
 /**
 * Returns the number of rows affected by the last SQL statement
 *
 * @access public
 * @return int the number of rows. 
 */
 public function rowCount()
 {
 return parent::rowCount();
 }
 
 /**
 * Set the default fetch mode for this statement
 *
 * @access public
 * @param  $PDO
 * @param  object $object 
 * @return bool 
 */
 public function setFetchMode()
 {
 $args = func_get_args();
 switch(func_num_args()) {
 case 1:
 return parent::setFetchMode($args[0]);
 break;
 case 2:
 return parent::setFetchMode($args[0], $args[1]);
 break;
 case 3:
 return parent::setFetchMode($args[0], $args[1], $args[2]);
 break;
 }
 }
 
 /**
 * Prevent users to clone the instance
 *
 * @access public
 * @return string trigger_error
 */
 public function __clone()
 {
 trigger_error('Clone is not allowed.', E_USER_ERROR);
 }
 }
 ?>
